/*******************************************************************************
 * Copyright (c) 2007 University of Oslo.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     University of Oslo - initial API and implementation
 *******************************************************************************/

package com.cea.papyrus.diagram.sequence.sedi.model.command;

import static com.cea.papyrus.diagram.sequence.sedi.model.util.ModelUtil.createUniqueName;

import java.util.List;

import org.eclipse.uml2.uml.Constraint;
import org.eclipse.uml2.uml.Interaction;
import org.eclipse.uml2.uml.InteractionFragment;
import org.eclipse.uml2.uml.Lifeline;
import org.eclipse.uml2.uml.OpaqueExpression;
import org.eclipse.uml2.uml.StateInvariant;
import org.eclipse.uml2.uml.UMLFactory;

import com.cea.papyrus.core.utils.Debug;
import com.cea.papyrus.diagram.sequence.sedi.model.util.OpaqueExpressionUtil;

/**
 * Command to create instances of StateInvariants.
 * 
 * <p>
 * The following attributes must be set for the command to complete
 * successfully:
 * </p>
 * <ul>
 * <li>Namespace
 * </ul>
 * 
 * <p>
 * The following attributes can be read to access the result of the command:
 * </p>
 * <ul>
 * <li>StateInvariants
 * </ul>
 * 
 * TODO Refactor - much code is shared with InteractionUse and other classes
 * that also are created within a namespace
 * 
 * @author Andreas Limyr
 * @author frankd@ifi.uio.no
 */
public class CreateStateInvariantCommand extends AbstractNamespaceCommand {

	private StateInvariant stateInvariant;
	private Lifeline coveredLifeline;
	
	public StateInvariant getStateInvariant() {
		return stateInvariant;
	}
	
	/**
	 * This method should not be used...
	 * use CreateStateInvariantCommand(
	 * 				Lifeline coveredLifeline, 
	 * 				InteractionFragment namespace)
	 * 
	 * instead
	 */
	public CreateStateInvariantCommand() {
		super();
		Debug.log(new Exception("This method should not be used."));
	}
	
	/**
	 * Main constructor
	 * @param coveredLifeline the {@link Lifeline} covered by the new {@link StateInvariant}
	 * @param namespace the {@link Interaction} where the {@link StateInvariant} is created
	 */
	public CreateStateInvariantCommand(Lifeline coveredLifeline, InteractionFragment namespace) {
		super();
		this.coveredLifeline = coveredLifeline;
		setNamespace(namespace);
	}

	@SuppressWarnings("unchecked")
	@Override
	public void execute() {
		List<InteractionFragment> fragments = getNamespaceFragments();

		stateInvariant = UMLFactory.eINSTANCE.createStateInvariant();
		stateInvariant.setName(createUniqueName(fragments, "StateInvariant"));
		stateInvariant.getCovereds().add(coveredLifeline);

		// Create a constraint for StateInvariant
		Constraint constraint = UMLFactory.eINSTANCE.createConstraint();
		constraint.setName(
				createUniqueName(
						stateInvariant.getOwnedElements(),
						"Constraint_"));
		OpaqueExpression valueSpec = 
			UMLFactory.eINSTANCE.createOpaqueExpression();
		valueSpec.setName(
				createUniqueName(
						constraint.getOwnedElements(),
						"ValueSpecification_"));
		OpaqueExpressionUtil.addBody(valueSpec, "ExpressionBody");
		constraint.setSpecification(valueSpec);
		
		stateInvariant.setInvariant(constraint);

		fragments.add(stateInvariant);
	}

	@Override
	public void undo() {
		getNamespaceFragments().remove(stateInvariant);
	}

	@Override
	public void redo() {
		getNamespaceFragments().add(stateInvariant);
	}

	@Override
	public void dispose() {
		stateInvariant = null;
		super.dispose();
	}
}
